package com.gws.juc;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 生产一个，消费一个
 * @author gws
 *
 */
class Aircondition{
	private int number = 0;
	//老版本锁synchronized
	/*public synchronized void increment() throws Exception{
		//1.判断  java中多线判断横向通知必须用while不能用if
		while(number != 0){
			this.wait();//线程等待
		}
		//2.干活
		number++;
		System.out.println(Thread.currentThread().getName()+": "+number);
		//3.通知
		this.notifyAll();//唤醒其它等待的线程
	}
	
	public synchronized void decrement() throws Exception{
		//1.判断
		while(number == 0){
			this.wait();//线程等待
		}
		//2.干活
		number--;
		System.out.println(Thread.currentThread().getName()+": "+number);
		//3.通知
		this.notifyAll();//唤醒其它等待的线程
	}*/
	//新版本
	private Lock lock = new ReentrantLock();
	private Condition condition = lock.newCondition();
	
	public void increment() throws Exception{
		lock.lock();
		try {
			//1.判断  java中多线判断横向通知必须用while不能用if
			while(number != 0){
				condition.await();//线程等待
			}
			//2.干活
			number++;
			System.out.println(Thread.currentThread().getName()+": "+number);
			//3.通知
			condition.signal();//唤醒其它等待的线程
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
		
	}
	
	public void decrement() throws Exception{
		lock.lock();
		try {
			//1.判断  java中多线判断横向通知必须用while不能用if
			while(number == 0){
				condition.await();//线程等待
			}
			//2.干活
			number--;
			System.out.println(Thread.currentThread().getName()+": "+number);
			//3.通知
			condition.signal();//唤醒其它等待的线程
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}
	
}
/**
 * 1 高聚低合前提下，线程操作资源类
 * 2 判断/干活/通知
 * 3 防止虚假唤醒
 * @author gws
 *
 */
public class ProdConsumerDemo04 {
	public static void main(String[] args) {
		Aircondition aircondition = new Aircondition();
		new Thread(() ->{
			try {
				for (int i = 0; i < 10; i++) {
					Thread.sleep(200);
					aircondition.increment();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}, "AAA").start();
		new Thread(() ->{
			try {
				for (int i = 0; i < 10; i++) {
					Thread.sleep(300);
					aircondition.decrement();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}, "BBB").start();
		new Thread(() ->{
			try {
				for (int i = 0; i < 10; i++) {
					Thread.sleep(400);
					aircondition.increment();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}, "CCC").start();
		new Thread(() ->{
			try {
				for (int i = 0; i < 10; i++) {
					Thread.sleep(200);
					aircondition.decrement();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}, "DDD").start();
		
	}

}
